fix: do not interrupt sync when cleaning invalid read-only items
authorMatthieu Gallien <matthieu.gallien@nextcloud.com>
Fri, 11 Apr 2025 09:33:45 +0000 (11:33 +0200)
committerbackportbot[bot] <backportbot[bot]@users.noreply.github.com>
Mon, 14 Apr 2025 16:38:43 +0000 (16:38 +0000)
Signed-off-by: Matthieu Gallien <matthieu.gallien@nextcloud.com>
src/gui/folder.cpp
src/gui/folder.h
src/libsync/discovery.cpp
src/libsync/filesystem.cpp
src/libsync/filesystem.h
src/libsync/syncengine.cpp
src/libsync/syncengine.h
test/testpermissions.cpp

index f89dab9c58289338d3fb8ce81358a0dda3ab931f..62aa980cd2ec23ffb27e864577e8175c2924b091 100644 (file)
@@ -107,8 +107,6 @@ Folder::Folder(const FolderDefinition &definition,
 
     connect(_engine.data(), &SyncEngine::aboutToRemoveAllFiles,
         this, &Folder::slotAboutToRemoveAllFiles);
-    connect(_engine.data(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders,
-            this, &Folder::slotNeedToRemoveRemnantsReadOnlyFolders);
     connect(_engine.data(), &SyncEngine::transmissionProgress, this, &Folder::slotTransmissionProgress);
     connect(_engine.data(), &SyncEngine::itemCompleted,
         this, &Folder::slotItemCompleted);
@@ -1723,34 +1721,6 @@ void Folder::slotAboutToRemoveAllFiles(SyncFileItem::Direction dir, std::functio
     msgBox->open();
 }
 
-void Folder::slotNeedToRemoveRemnantsReadOnlyFolders(const QList<SyncFileItemPtr> &folders,
-                                                     const QString &localPath,
-                                                     std::function<void (bool)> callback)
-{
-    auto listOfFolders = QStringList{};
-    for (const auto &oneFolder : folders) {
-        listOfFolders.push_back(oneFolder->_file);
-    }
-
-    qCInfo(lcFolder()) << "will delete invalid read-only folders:" << listOfFolders.join(", ");
-
-    setSyncPaused(true);
-    for(const auto &oneFolder : folders) {
-        const auto fileInfo = QFileInfo{localPath + oneFolder->_file};
-        const auto parentFolderPath = fileInfo.dir().absolutePath();
-        const auto parentPermissionsHandler = FileSystem::FilePermissionsRestore{parentFolderPath, FileSystem::FolderPermissions::ReadWrite};
-        if (oneFolder->_type == ItemType::ItemTypeDirectory) {
-            FileSystem::removeRecursively(localPath + oneFolder->_file);
-        } else {
-            FileSystem::remove(localPath + oneFolder->_file);
-        }
-    }
-    callback(true);
-    setSyncPaused(false);
-    _lastEtag.clear();
-    slotScheduleThisFolder();
-}
-
 void Folder::removeLocalE2eFiles()
 {
     qCDebug(lcFolder) << "Removing local E2EE files";
index 741ce76b10dfa1264c3695a024f6868ff59f218d..f66d4c81ba1a056970dd995396035676ed40f608 100644 (file)
@@ -336,10 +336,6 @@ public slots:
     // connected to the corresponding signals in the SyncEngine
     void slotAboutToRemoveAllFiles(OCC::SyncFileItem::Direction, std::function<void(bool)> callback);
 
-    void slotNeedToRemoveRemnantsReadOnlyFolders(const QList<SyncFileItemPtr> &folders,
-                                                 const QString &localPath,
-                                                 std::function<void(bool)> callback);
-
     /**
       * Starts a sync operation
       *
index 4c0dfa151f8d5f64a7b7041385aeebde164aeb5d..b3fedf6da4c35a518ecc3b77fbd85baa3e9382d1 100644 (file)
@@ -1867,16 +1867,14 @@ bool ProcessDirectoryJob::checkPermissions(const OCC::SyncFileItemPtr &item)
             // No permissions set
             return true;
         } else if (item->isDirectory() && !perms.hasPermission(RemotePermissions::CanAddSubDirectories)) {
-            qCWarning(lcDisco) << "checkForPermission: ERROR" << item->_file;
-            item->_instruction = CSYNC_INSTRUCTION_ERROR;
+            qCWarning(lcDisco) << "checkForPermission: Not allowed because you don't have permission to add subfolders to that folder:" << item->_file;
+            item->_instruction = CSYNC_INSTRUCTION_IGNORE;
             item->_errorString = tr("Not allowed because you don't have permission to add subfolders to that folder");
-            const auto localPath = QString{_discoveryData->_localDir + item->_file};
-            qCWarning(lcDisco) << "unexpected new folder in a read-only folder will be made read-write" << localPath;
             emit _discoveryData->remnantReadOnlyFolderDiscovered(item);
             return false;
         } else if (!item->isDirectory() && !perms.hasPermission(RemotePermissions::CanAddFile)) {
-            qCWarning(lcDisco) << "checkForPermission: ERROR" << item->_file;
-            item->_instruction = CSYNC_INSTRUCTION_ERROR;
+            qCWarning(lcDisco) << "checkForPermission: Not allowed because you don't have permission to add files in that folder:" << item->_file;
+            item->_instruction = CSYNC_INSTRUCTION_IGNORE;
             item->_errorString = tr("Not allowed because you don't have permission to add files in that folder");
             emit _discoveryData->remnantReadOnlyFolderDiscovered(item);
             return false;
@@ -2072,11 +2070,10 @@ int ProcessDirectoryJob::processSubJobs(int nbJobs)
                 if (perms.isNull()) {
                     // No permissions set
                 } else if (_dirItem->isDirectory() && !perms.hasPermission(RemotePermissions::CanAddSubDirectories)) {
-                    qCWarning(lcDisco) << "checkForPermission: ERROR" << _dirItem->_file;
-                    _dirItem->_instruction = CSYNC_INSTRUCTION_ERROR;
+                    qCWarning(lcDisco) << "checkForPermission: Not allowed because you don't have permission to add subfolders to that folder: " << _dirItem->_file;
+                    _dirItem->_instruction = CSYNC_INSTRUCTION_IGNORE;
                     _dirItem->_errorString = tr("Not allowed because you don't have permission to add subfolders to that folder");
                     const auto localPath = QString{_discoveryData->_localDir + _dirItem->_file};
-                    qCWarning(lcDisco) << "unexpected new folder in a read-only folder will be made read-write" << localPath;
                     emit _discoveryData->remnantReadOnlyFolderDiscovered(_dirItem);
                 }
 
index 59f375ed246abf701a8aa4f360d3e363ed1627b2..5371ae35a02a424325359656a8084975439ef1cb 100644 (file)
@@ -254,9 +254,13 @@ qint64 FileSystem::getSize(const QString &filename)
 }
 
 // Code inspired from Qt5's QDir::removeRecursively
-bool FileSystem::removeRecursively(const QString &path, const std::function<void(const QString &path, bool isDir)> &onDeleted, QStringList *errors)
+bool FileSystem::removeRecursively(const QString &path, const std::function<void(const QString &path, bool isDir)> &onDeleted, QStringList *errors, const std::function<void(const QString &path, bool isDir)> &onError)
 {
-    FileSystem::setFolderPermissions(path, FileSystem::FolderPermissions::ReadWrite);
+    if (!FileSystem::setFolderPermissions(path, FileSystem::FolderPermissions::ReadWrite)) {
+        if (onError) {
+            onError(path, true);
+        }
+    }
 
     bool allRemoved = true;
     QDirIterator di(path, QDir::AllEntries | QDir::Hidden | QDir::System | QDir::NoDotAndDotDot);
@@ -269,7 +273,7 @@ bool FileSystem::removeRecursively(const QString &path, const std::function<void
         // we never want to go into this branch for .lnk files
         bool isDir = FileSystem::isDir(fi.absoluteFilePath()) && !FileSystem::isSymLink(fi.absoluteFilePath()) && !FileSystem::isJunction(fi.absoluteFilePath());
         if (isDir) {
-            removeOk = removeRecursively(path + QLatin1Char('/') + di.fileName(), onDeleted, errors); // recursive
+            removeOk = removeRecursively(path + QLatin1Char('/') + di.fileName(), onDeleted, errors, onError); // recursive
         } else {
             QString removeError;
 
@@ -285,6 +289,9 @@ bool FileSystem::removeRecursively(const QString &path, const std::function<void
                     errors->append(QCoreApplication::translate("FileSystem", "Error removing \"%1\": %2")
                                        .arg(QDir::toNativeSeparators(di.filePath()), removeError));
                 }
+                if (onError) {
+                    onError(di.filePath(), false);
+                }
                 qCWarning(lcFileSystem) << "Error removing " << di.filePath() << ':' << removeError;
             }
         }
@@ -305,6 +312,9 @@ bool FileSystem::removeRecursively(const QString &path, const std::function<void
                 errors->append(QCoreApplication::translate("FileSystem", "Could not remove folder \"%1\"")
                                    .arg(QDir::toNativeSeparators(path)));
             }
+            if (onError) {
+                onError(di.filePath(), false);
+            }
             qCWarning(lcFileSystem) << "Error removing folder" << path;
         }
     }
index e0439b8f52be4955f33013dd9b9e77b19edc2649..26c999994394f48bd70eb88f5f51b9324b0267e3 100644 (file)
@@ -122,8 +122,9 @@ namespace FileSystem {
      * errors are collected in errors.
      */
     bool OWNCLOUDSYNC_EXPORT removeRecursively(const QString &path,
-        const std::function<void(const QString &path, bool isDir)> &onDeleted = nullptr,
-        QStringList *errors = nullptr);
+                                               const std::function<void(const QString &path, bool isDir)> &onDeleted = nullptr,
+                                               QStringList *errors = nullptr,
+                                               const std::function<void(const QString &path, bool isDir)> &onError = nullptr);
 
     bool OWNCLOUDSYNC_EXPORT setFolderPermissions(const QString &path,
                                                   FileSystem::FolderPermissions permissions) noexcept;
index 9319116312b3b2c91fc5ea93b8a747cf943ac32a..e24ce8a308b1ebd6c1b24f66029ad675e6e0e7b4 100644 (file)
@@ -840,7 +840,6 @@ void SyncEngine::slotDiscoveryFinished()
 
     if (!_remnantReadOnlyFolders.isEmpty()) {
         handleRemnantReadOnlyFolders();
-        return;
     }
 
     finishSync();
@@ -1169,9 +1168,29 @@ bool SyncEngine::handleMassDeletion()
 
 void SyncEngine::handleRemnantReadOnlyFolders()
 {
-    promptUserBeforePropagation([this](auto &&callback) {
-                                    emit aboutToRemoveRemnantsReadOnlyFolders(_remnantReadOnlyFolders, _localPath, callback);
-                                });
+    auto listOfFolders = QStringList{};
+    for (const auto &oneFolder : std::as_const(_remnantReadOnlyFolders)) {
+        listOfFolders.push_back(oneFolder->_file);
+    }
+
+    qCInfo(lcEngine()) << "will delete invalid read-only folders:" << listOfFolders.join(", ");
+
+    for(const auto &oneFolder : std::as_const(_remnantReadOnlyFolders)) {
+        const auto fileInfo = QFileInfo{_localPath + oneFolder->_file};
+        const auto parentFolderPath = fileInfo.dir().absolutePath();
+        slotAddTouchedFile(parentFolderPath);
+        const auto parentPermissionsHandler = FileSystem::FilePermissionsRestore{parentFolderPath, FileSystem::FolderPermissions::ReadWrite};
+        slotAddTouchedFile(_localPath + oneFolder->_file);
+
+        if (oneFolder->_type == ItemType::ItemTypeDirectory) {
+            const auto deletionCallback = [this] (const QString &deleteItem, bool) {
+                slotAddTouchedFile(deleteItem);
+            };
+            FileSystem::removeRecursively(_localPath + oneFolder->_file, deletionCallback, nullptr, deletionCallback);
+        } else {
+            FileSystem::remove(_localPath + oneFolder->_file);
+        }
+    }
 }
 
 template <typename T>
index 76fc99ce7dc54c7c2c540255ca2598ff3b44127b..92ef9fd7a74e7bfaa6c4c4d8f8d29853fdb34cdc 100644 (file)
@@ -190,10 +190,6 @@ signals:
      */
     void aboutToRemoveAllFiles(OCC::SyncFileItem::Direction direction, std::function<void(bool)> f);
 
-    void aboutToRemoveRemnantsReadOnlyFolders(const QList<SyncFileItemPtr> &folders,
-                                              const QString &localPath,
-                                              std::function<void(bool)> f);
-
     // A new folder was discovered and was not synced because of the confirmation feature
     void newBigFolder(const QString &folder, bool isExternal);
 
index 5a1345741ee7fe4bdb36fad4a0e0f5ca83c35fb8..8e457e0b65c66e466d061b0c66fc2c7f497dcfd2 100644 (file)
@@ -94,14 +94,6 @@ private slots:
         FakeFolder fakeFolder{ FileInfo() };
         QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
 
-        QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders,
-                         [&](const QList<SyncFileItemPtr> &folders, const QString &localPath, std::function<void(bool)> callback) {
-                             qDebug() << "aboutToRemoveRemnantsReadOnlyFolders called";
-                             Q_UNUSED(folders);
-                             Q_UNUSED(localPath);
-                             callback(false);
-                         });
-
         // Some of this test depends on the order of discovery. With threading
         // that order becomes effectively random, but we want to make sure to test
         // all cases and thus disable threading.
@@ -281,14 +273,14 @@ private slots:
 
         applyPermissionsFromName(fakeFolder.remoteModifier());
         // error: can't upload to readonly
-        QVERIFY(!fakeFolder.syncOnce());
+        QVERIFY(fakeFolder.syncOnce());
 
         assertCsyncJournalOk(fakeFolder.syncJournal());
         currentLocalState = fakeFolder.currentLocalState();
 
         //6.
-        // The file should not exist on the remote, but still be there
-        QVERIFY(currentLocalState.find("readonlyDirectory_PERM_M_/newFile_PERM_WDNV_.data"));
+        // The file should not exist on the remote, and not be there
+        QVERIFY(!currentLocalState.find("readonlyDirectory_PERM_M_/newFile_PERM_WDNV_.data"));
         QVERIFY(!fakeFolder.currentRemoteState().find("readonlyDirectory_PERM_M_/newFile_PERM_WDNV_.data"));
         // remove it so next test succeed.
         removeReadOnly("readonlyDirectory_PERM_M_/newFile_PERM_WDNV_.data");
@@ -362,8 +354,8 @@ private slots:
         //2. move a directory from read to read only  (move the directory from previous step)
         renameReadOnly("normalDirectory_PERM_CKDNV_/subdir_PERM_CKDNV_", "readonlyDirectory_PERM_M_/moved_PERM_CK_" );
 
-        // error: can't upload to readonly!
-        QVERIFY(!fakeFolder.syncOnce());
+        // can't upload to readonly but not an error
+        QVERIFY(fakeFolder.syncOnce());
         currentLocalState = fakeFolder.currentLocalState();
 
         //1.
@@ -371,8 +363,8 @@ private slots:
         QVERIFY(currentLocalState.find("readonlyDirectory_PERM_M_/subdir_PERM_CK_" ));
         // including contents
         QVERIFY(currentLocalState.find("readonlyDirectory_PERM_M_/subdir_PERM_CK_/subsubdir_PERM_CKDNV_/normalFile_PERM_WVND_.data" ));
-        // new still exist
-        QVERIFY(currentLocalState.find("readonlyDirectory_PERM_M_/newname_PERM_CK_/subsubdir_PERM_CKDNV_/normalFile_PERM_WVND_.data" ));
+        // new no longer exists
+        QVERIFY(!currentLocalState.find("readonlyDirectory_PERM_M_/newname_PERM_CK_/subsubdir_PERM_CKDNV_/normalFile_PERM_WVND_.data" ));
         // but is not on server: so remove it locally for the future comparison
         removeReadOnly("readonlyDirectory_PERM_M_/newname_PERM_CK_");
 
@@ -381,8 +373,8 @@ private slots:
         QVERIFY(!currentLocalState.find("normalDirectory_PERM_CKDNV_/subdir_PERM_CKDNV_"));
         // but still on the server: the rename causing an error meant the deletes didn't execute
         QVERIFY(fakeFolder.currentRemoteState().find("normalDirectory_PERM_CKDNV_/subdir_PERM_CKDNV_"));
-        // new still there
-        QVERIFY(currentLocalState.find("readonlyDirectory_PERM_M_/moved_PERM_CK_/subsubdir_PERM_CKDNV_/normalFile_PERM_WVND_.data" ));
+        // new no longer exists
+        QVERIFY(!currentLocalState.find("readonlyDirectory_PERM_M_/moved_PERM_CK_/subsubdir_PERM_CKDNV_/normalFile_PERM_WVND_.data" ));
         //but not on server
         removeReadOnly("readonlyDirectory_PERM_M_/moved_PERM_CK_");
         fakeFolder.remoteModifier().remove("normalDirectory_PERM_CKDNV_/subdir_PERM_CKDNV_");
@@ -438,13 +430,6 @@ private slots:
     {
         FakeFolder fakeFolder{FileInfo{}};
 
-        QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders,
-                         [&](const QList<SyncFileItemPtr> &folders, const QString &localPath, std::function<void(bool)> callback) {
-                             Q_UNUSED(folders)
-                             Q_UNUSED(localPath)
-                             callback(false);
-                         });
-
         // Some of this test depends on the order of discovery. With threading
         // that order becomes effectively random, but we want to make sure to test
         // all cases and thus disable threading.
@@ -503,11 +488,11 @@ private slots:
         SyncFileItemVector discovery;
         connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToPropagate, this, [&discovery](auto v) { discovery = v; });
         ItemCompletedSpy completeSpy(fakeFolder);
-        QVERIFY(!fakeFolder.syncOnce());
+        QVERIFY(fakeFolder.syncOnce());
 
         // if renaming doesn't work, just delete+create
         QVERIFY(itemInstruction(completeSpy, "norename/file", CSYNC_INSTRUCTION_REMOVE));
-        QVERIFY(itemInstruction(completeSpy, "norename/sub", CSYNC_INSTRUCTION_NONE));
+        QVERIFY(itemInstruction(completeSpy, "norename/sub", CSYNC_INSTRUCTION_REMOVE));
         QVERIFY(discoveryInstruction(discovery, "norename/sub", CSYNC_INSTRUCTION_REMOVE));
         QVERIFY(itemInstruction(completeSpy, "norename/file_renamed", CSYNC_INSTRUCTION_NEW));
         QVERIFY(itemInstruction(completeSpy, "norename/sub_renamed", CSYNC_INSTRUCTION_NEW));
@@ -516,19 +501,19 @@ private slots:
 
         // simiilarly forbidding moves becomes delete+create
         QVERIFY(itemInstruction(completeSpy, "nomove/file", CSYNC_INSTRUCTION_REMOVE));
-        QVERIFY(itemInstruction(completeSpy, "nomove/sub", CSYNC_INSTRUCTION_NONE));
+        QVERIFY(itemInstruction(completeSpy, "nomove/sub", CSYNC_INSTRUCTION_REMOVE));
         QVERIFY(discoveryInstruction(discovery, "nomove/sub", CSYNC_INSTRUCTION_REMOVE));
         // nomove/sub/file is removed as part of the dir
         QVERIFY(itemInstruction(completeSpy, "allowed/file_moved", CSYNC_INSTRUCTION_NEW));
         QVERIFY(itemInstruction(completeSpy, "allowed/sub_moved", CSYNC_INSTRUCTION_NEW));
         QVERIFY(itemInstruction(completeSpy, "allowed/sub_moved/file", CSYNC_INSTRUCTION_NEW));
 
-        // when moving to an invalid target, the targets should be an error
-        QVERIFY(itemInstruction(completeSpy, "nocreatefile/file", CSYNC_INSTRUCTION_ERROR));
-        QVERIFY(itemInstruction(completeSpy, "nocreatefile/zfile", CSYNC_INSTRUCTION_ERROR));
+        // when moving to an invalid target, the targets should be ignored
+        QVERIFY(itemInstruction(completeSpy, "nocreatefile/file", CSYNC_INSTRUCTION_IGNORE));
+        QVERIFY(itemInstruction(completeSpy, "nocreatefile/zfile", CSYNC_INSTRUCTION_IGNORE));
         QVERIFY(itemInstruction(completeSpy, "nocreatefile/sub", CSYNC_INSTRUCTION_RENAME)); // TODO: What does a real server say?
-        QVERIFY(itemInstruction(completeSpy, "nocreatedir/sub2", CSYNC_INSTRUCTION_ERROR));
-        QVERIFY(itemInstruction(completeSpy, "nocreatedir/zsub2", CSYNC_INSTRUCTION_ERROR));
+        QVERIFY(itemInstruction(completeSpy, "nocreatedir/sub2", CSYNC_INSTRUCTION_IGNORE));
+        QVERIFY(itemInstruction(completeSpy, "nocreatedir/zsub2", CSYNC_INSTRUCTION_IGNORE));
 
         // and the sources of the invalid moves should be restored, not deleted
         // (depending on the order of discovery a follow-up sync is needed)
@@ -541,12 +526,12 @@ private slots:
 
         // A follow-up sync will restore allowed/file and allowed/sub2 and maintain the nocreatedir/file errors
         completeSpy.clear();
-        QVERIFY(!fakeFolder.syncOnce());
+        QVERIFY(fakeFolder.syncOnce());
 
-        QVERIFY(itemInstruction(completeSpy, "nocreatefile/file", CSYNC_INSTRUCTION_ERROR));
-        QVERIFY(itemInstruction(completeSpy, "nocreatefile/zfile", CSYNC_INSTRUCTION_ERROR));
-        QVERIFY(itemInstruction(completeSpy, "nocreatedir/sub2", CSYNC_INSTRUCTION_ERROR));
-        QVERIFY(itemInstruction(completeSpy, "nocreatedir/zsub2", CSYNC_INSTRUCTION_ERROR));
+        QVERIFY(itemInstruction(completeSpy, "nocreatefile/file", CSYNC_INSTRUCTION_NONE));
+        QVERIFY(itemInstruction(completeSpy, "nocreatefile/zfile", CSYNC_INSTRUCTION_NONE));
+        QVERIFY(itemInstruction(completeSpy, "nocreatedir/sub2", CSYNC_INSTRUCTION_NONE));
+        QVERIFY(itemInstruction(completeSpy, "nocreatedir/zsub2", CSYNC_INSTRUCTION_NONE));
 
         QVERIFY(itemInstruction(completeSpy, "allowed/file", CSYNC_INSTRUCTION_NEW));
         QVERIFY(itemInstruction(completeSpy, "allowed/sub2", CSYNC_INSTRUCTION_NEW));
@@ -564,14 +549,6 @@ private slots:
     {
         FakeFolder fakeFolder{FileInfo{}};
 
-        QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders,
-                         [&](const QList<SyncFileItemPtr> &folders, const QString &localPath, std::function<void(bool)> callback) {
-                             for(const auto &oneFolder : folders) {
-                                 FileSystem::removeRecursively(localPath + oneFolder->_file);
-                             }
-                             callback(false);
-                         });
-
         auto &lm = fakeFolder.localModifier();
         auto &rm = fakeFolder.remoteModifier();
         rm.mkdir("forbidden-move");
@@ -623,14 +600,6 @@ private slots:
     {
         FakeFolder fakeFolder{FileInfo{}};
 
-        QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders,
-                         [&](const QList<SyncFileItemPtr> &folders, const QString &localPath, std::function<void(bool)> callback) {
-                             for(const auto &oneFolder : folders) {
-                                 FileSystem::removeRecursively(localPath + oneFolder->_file);
-                             }
-                             callback(false);
-                         });
-
         auto &remote = fakeFolder.remoteModifier();
 
         remote.mkdir("readOnlyFolder");
@@ -648,14 +617,6 @@ private slots:
     {
         FakeFolder fakeFolder{FileInfo{}};
 
-        QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders,
-                         [&](const QList<SyncFileItemPtr> &folders, const QString &localPath, std::function<void(bool)> callback) {
-                             for(const auto &oneFolder : folders) {
-                                 FileSystem::removeRecursively(localPath + oneFolder->_file);
-                             }
-                             callback(false);
-                         });
-
         auto &remote = fakeFolder.remoteModifier();
 
         remote.mkdir("readWriteFolder");
@@ -674,14 +635,6 @@ private slots:
     {
         FakeFolder fakeFolder{FileInfo{}};
 
-        QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders,
-                         [&](const QList<SyncFileItemPtr> &folders, const QString &localPath, std::function<void(bool)> callback) {
-                             for(const auto &oneFolder : folders) {
-                                 FileSystem::removeRecursively(localPath + oneFolder->_file);
-                             }
-                             callback(false);
-                         });
-
         auto &remote = fakeFolder.remoteModifier();
 
         remote.mkdir("testFolder");
@@ -718,14 +671,6 @@ private slots:
     {
         FakeFolder fakeFolder{FileInfo{}};
 
-        QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders,
-                         [&](const QList<SyncFileItemPtr> &folders, const QString &localPath, std::function<void(bool)> callback) {
-                             for(const auto &oneFolder : folders) {
-                                 FileSystem::removeRecursively(localPath + oneFolder->_file);
-                             }
-                             callback(false);
-                         });
-
         auto &remote = fakeFolder.remoteModifier();
 
         remote.mkdir("testFolder");
@@ -786,14 +731,6 @@ private slots:
     {
         FakeFolder fakeFolder{FileInfo{}};
 
-        QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders,
-                         [&](const QList<SyncFileItemPtr> &folders, const QString &localPath, std::function<void(bool)> callback) {
-                             for(const auto &oneFolder : folders) {
-                                 FileSystem::removeRecursively(localPath + oneFolder->_file);
-                             }
-                             callback(false);
-                         });
-
         auto &remote = fakeFolder.remoteModifier();
 
         remote.mkdir("readOnlyFolder");
@@ -824,14 +761,6 @@ private slots:
     {
         FakeFolder fakeFolder{FileInfo{}};
 
-        QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders,
-                         [&](const QList<SyncFileItemPtr> &folders, const QString &localPath, std::function<void(bool)> callback) {
-                             for(const auto &oneFolder : folders) {
-                                 FileSystem::removeRecursively(localPath + oneFolder->_file);
-                             }
-                             callback(false);
-                         });
-
         auto &remote = fakeFolder.remoteModifier();
 
         remote.mkdir("readOnlyFolder");
@@ -864,14 +793,6 @@ private slots:
     {
         FakeFolder fakeFolder{FileInfo{}};
 
-        QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders,
-                         [&](const QList<SyncFileItemPtr> &folders, const QString &localPath, std::function<void(bool)> callback) {
-                             for(const auto &oneFolder : folders) {
-                                 FileSystem::removeRecursively(localPath + oneFolder->_file);
-                             }
-                             callback(false);
-                         });
-
         auto &remote = fakeFolder.remoteModifier();
 
         remote.mkdir("readOnlyFolder");
@@ -907,14 +828,6 @@ private slots:
     {
         FakeFolder fakeFolder{FileInfo{}};
 
-        QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders,
-                         [&](const QList<SyncFileItemPtr> &folders, const QString &localPath, std::function<void(bool)> callback) {
-                             for(const auto &oneFolder : folders) {
-                                 FileSystem::removeRecursively(localPath + oneFolder->_file);
-                             }
-                             callback(false);
-                         });
-
         auto &remote = fakeFolder.remoteModifier();
 
         remote.mkdir("readOnlyFolder");